<template>
  <div>
    <div class="mb-10" v-if="$slots.default">
      <slot />
    </div>
    <el-row class="mb-10" v-if="$slots.btns">
      <el-col :span="22">
        <slot name="btns"></slot>
      </el-col>
      <el-col :span="2"></el-col>
    </el-row>
    <div v-loading="loading">
      <slot
        name="table"
        v-if="$slots.table || $scopedSlots.table"
        v-bind="{ list, pageNo, pageSize, total }"
      ></slot>
      <el-table v-else :data="list">
        <el-table-column
          v-for="col in columns"
          v-bind="col"
          :key="col.label"
        ></el-table-column>
        <EmptyNode slot="empty" />
      </el-table>
    </div>
    <div v-if="pagination" class="custom-pagination">
      <div>共 {{ total }} 条</div>
      <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page.sync="pageNo"
        :page-sizes="pagination.pageSizes"
        :page-size="pagination.pageSize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
      ></el-pagination>
    </div>
  </div>
</template>

<script lang="ts">
/**
 * slot 说明
 *  * btns 用于自定义左上角内容，如新增，生成图表等按钮
 *  * table 自定义table
 *
 */
import { Vue, Component, Prop, Inject } from 'vue-property-decorator'
import EmptyNode from '../emptyNode/index.vue'

// import FilterTool from '@/components/FilterTool/index.vue'

const DEFAULT_PAGINATION = {
  pageNo: 1,
  pageSize: 10,
  pageSizes: [10, 20, 50],
  names: {
    pageNo: 'pageNo',
    pageSize: 'pageSize'
  }
}

const DEFAULT_PARAMS_MAPPING = {
  pageNo: 'pageNo',
  pageSize: 'pageSize'
}
// 所有的数据接口返回格式如下
type ListResult = { list: any[]; total: number }
type PaginationType = typeof DEFAULT_PAGINATION
type ListFunction = { (query?: any): Promise<ListResult> }
type ParamsType = typeof DEFAULT_PARAMS_MAPPING

@Component({
  name: 'PaginationTable',
  components: {
    EmptyNode
  }
})
export default class extends Vue {
  // 若提供ower依赖，会自动为其注册refreshTable方法，方便再外部手动刷新
  @Inject({ default: null }) ower?: any
  // 表列
  @Prop({ default: () => [] }) columns?: any[]
  // 自定义查询参数，将合并到{pageNo,pageSize}中
  @Prop({ default: () => ({}) }) params?: object
  // 数据获取接口
  @Prop() getList?: ListFunction
  // 分页配置
  @Prop({
    default: () => {
      return { ...DEFAULT_PAGINATION }
    }
  })
  pagination?: PaginationType
  @Prop({
    default: true
  })
  // 是否再挂载时自动加载数据
  loadOnMounted?: boolean

  @Prop({
    default: () => ({ ...DEFAULT_PARAMS_MAPPING })
  })
  paramsMapping!: ParamsType
  // 当前页数
  pageNo = 1
  // 分页大小
  pageSize = 10
  // 数据总数
  total = 0
  // 当前页数据
  list: any[] = []
  // 加载状态
  loading = false
  mounted() {
    if (this.pagination) {
      this.pageNo = this.pagination.pageNo || this.pageNo
      this.pageSize = this.pagination.pageSize || this.pageSize
    }
    if (this.ower) {
      this.ower['refreshTable'] = (pagination: PaginationType) => {
        if (pagination) {
          this.pageNo = pagination.pageNo || this.pageNo
          this.pageSize = pagination.pageSize || this.pageSize
        }
        this.query()
      }
      this.ower['resetTable'] = () => {
        this.pageNo = 1
        this.total = 0
        this.list = []
      }
    }
    this.$nextTick(() => {
      this.loadOnMounted && this.query()
    })
  }
  async query() {
    if (!this.getList) {
      return
    }
    this.loading = true
    const { pageNo, pageSize } = this

    const pageSizeName =
      this.paramsMapping.pageSize || DEFAULT_PARAMS_MAPPING.pageSize
    const pageNoName =
      this.paramsMapping.pageNo || DEFAULT_PARAMS_MAPPING.pageNo
    const ps = {
      [pageSizeName]: pageSize,
      [pageNoName]: pageNo
    }

    try {
      const res = await this.getList(Object.assign(ps, this.params))
      const { list, total } = res
      Object.assign(this, { list, total })
    } catch (err) {
      console.log(err)
    }
    this.loading = false
  }
  private handleSizeChange(val: any) {
    this.pageNo = 1
    this.pageSize = val
    this.query()
  }
  handleCurrentChange(val: number) {
    this.pageNo = val
    this.query()
  }

  /**
   * TODO 用于统一查询组件
   */
  handleFilter(params: any) {
    this.$emit('updatefilterQuery', params)
    this.$emit('updatePanigationQuery', {
      pageNo: 1
    })
    this.$emit('queryList')
  }
}
@Component({
  provide() {
    return {
      ower: this
    }
  }
})
export class mixin extends Vue {
  list: any[] = []
  searchModel: any = {}

  refresh() {
    //@ts-ignore
    this.refreshTable({
      pageNo: 1
    })
  }

  reset() {
    //@ts-ignore
    this.resetTable()
    if (typeof this.list !== 'undefined') {
      this.list = []
    }
  }
}
</script>
<style lang="scss">
.custom-pagination {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: #f5f5f5;
  padding: 10px 24px;
  margin-top: 2px;
  height: 48px;
  .el-pagination__total {
    display: none !important;
  }
  li,
  button {
    background: transparent !important;
  }
}
</style>
